#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "cJSON.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <stdbool.h>

int main(int argc, char const *argv[])
{
    //接收qt传来的广播
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    // 3.指定多播的IP和端口
    struct sockaddr_in dev_addr;
    dev_addr.sin_family = AF_INET;
    dev_addr.sin_port = htons(8887);
    dev_addr.sin_addr.s_addr = INADDR_ANY;
    socklen_t addrlen = sizeof(dev_addr);
    // 4.绑定
    if (bind(sockfd, (struct sockaddr *)&dev_addr, addrlen) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok\n");
    //收到了搜索包
    ssize_t len = -1;
    char buf[128] = {0};
    struct sockaddr_in soft_addr;
    memset(buf, 0, 128);
    //收到了qt的搜索报
    len = recvfrom(sockfd, buf, 128, 0, (struct sockaddr *)&soft_addr, &addrlen);
    //需要回复qt:"yes"
    sendto(sockfd, "yes", strlen(buf), 0, (struct sockaddr *)&soft_addr, addrlen);
    //成为服务器 等待qt进行tcp链接
    // 1.创建流式套接字（socket）-----------------------------》有手机
    int serverfd = socket(AF_INET, SOCK_STREAM, 0);
    if (serverfd < 0)
    {
        perror("sock err");
        return -1;
    }
    printf("serverfd:%d\n", serverfd);
    //INADDR_ANY:0.0.0.0
    // 3.绑定套接字（bind）--------------------------------------》绑定手机
    if (bind(serverfd, (struct sockaddr *)&dev_addr, addrlen) < 0)
    {
        perror("bind err");
        return -1;
    }
    printf("bind ok\n");
    // 4.监听套接字（listen）-------------------------------------》待机
    //将主动套接字变成被动套接字
    if (listen(serverfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok\n");
    // 5.接收客户端请求（accept）-----------------------------》接电话
    //sockfd:用于链接
    //acceptfd:用于通信
    int acceptfd;
    struct sockaddr_in cliaddr;
    int ret;

    acceptfd = accept(serverfd, (struct sockaddr *)&cliaddr, &addrlen);
    if (acceptfd < 0)
    {
        perror("accept err");
        return -1;
    }
    printf("qt连入\n");
    // 6.发送、接收消息（send、recv）-----------------------》通话
    //接收qt发送json文件判断是否拥有点表
    while (1)
    {
        int ret = recv(acceptfd, buf, 128, 0);
        if (ret <= 0)
        {
            break;
        }
        //将接收到的json文件反序列化判断type
        printf("%s\n", buf);
        //获取跟节点
        cJSON *root = cJSON_Parse(buf);
        cJSON *item = cJSON_GetObjectItem(root, "type");
        printf("%s:%d\n", item->string, item->valueint);
        // sleep(10);
        if (item->valueint == 1)
        {
            //查看是否拥有点表文件
            int fd = open("./config.json", O_RDONLY | O_WRONLY);
            if (fd < 0)
            {
                //printf("fd<0 start");
                fd = open("./config.json", O_RDONLY | O_WRONLY | O_CREAT, 0666);
                //没有config.json点表文件需要qt传点表，序列化json
                //创建root根节点
                cJSON *root = cJSON_CreateObject();
                //创建节点并添加到根节点中
                cJSON_AddNumberToObject(root, "type", 1);
                cJSON_AddNumberToObject(root, "result", 0);
                cJSON_AddBoolToObject(root, "up_config", true);
                //将json发送给qt
                char *p = cJSON_Print(root);
                printf("%s\n", p);
                p[strlen(p)] = '\0';
                send(acceptfd, p, strlen(p), 0);
                //接收qt发送来的点表文件，创建config.json
                int recvsize = 0;
                while ((recvsize = recv(acceptfd, buf, 128, 0)) > 0)
                {
                    // printf("%s\n",buf);
                    write(fd, buf, recvsize);
                    memset(buf, 0, 128);
                }
                close(fd);
                cJSON_Delete(root);
                free(p);
            }
            else
            {
                //创建root根节点
                cJSON *root = cJSON_CreateObject();
                //有点表文件不需要qt传点表
                cJSON_AddNumberToObject(root, "type", 1);
                cJSON_AddNumberToObject(root, "result", 0);
                cJSON_AddBoolToObject(root, "up_config", false);
                //将json发送给qt
                char *p = cJSON_Print(root);
                printf("%s\n", p);
                send(acceptfd, p, strlen(p), 0);
                cJSON_Delete(root);
                free(p);
            }
        }
        else if (item->valueint == 3)
        {
            //接收qt传来的心跳包文件
            int ret = recv(acceptfd, buf, 128, 0);
            if(ret < 0)
            {
                break;
            }

            printf("%s\n", buf);
            send(acceptfd, "i am alive", 128, 0);
            memset(buf,0,128);
        }
    }
    close(acceptfd);
    // 5.关闭套接字（close）
    close(sockfd);
    return 0;
}